package com.sugon.modules.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.util.StrUtil;
import com.sugon.modules.device.model.dto.*;

import java.util.*;

/**
 * @author ： YuXD
 * @description： 日期工具类
 * @date ： 2020-07-18 上午 9:46
 * @version: 1.0
 */
public class DateUtil {

    /**
     * 生成近多少天的日期列表，注意：不包含今天
     * 如果days 大于0 ，则表示获取过去多少天
     * 小于0 ，则表示将来多少天
     *
     * @param days 天数，近多少天
     * @return
     */
    public static List<String> generateDateList(Integer days) {
        List<String> dateList = CollectionUtil.newArrayList();
        DateTime today = cn.hutool.core.date.DateUtil.date();
        if (days >= 0) {
            Date pastDay = cn.hutool.core.date.DateUtil.offsetDay(today, -days);
            for (int i = 0; i < days; i++) {
                dateList.add(cn.hutool.core.date.DateUtil.formatDate(cn.hutool.core.date.DateUtil.offsetDay(pastDay, i)));
            }
        } else {
            days = Math.abs(days);
            for (int i = 1; i <= days; i++) {
                dateList.add(cn.hutool.core.date.DateUtil.formatDate(cn.hutool.core.date.DateUtil.offsetDay(today, i)));
            }
        }
        return dateList;
    }

    /**
     * 返回指定日期的月份，如果不传则返回当前月份的
     *
     * @param date
     * @return
     */
    public static int month(Date date) {
        if (date == null) {
            date = new Date();
        }
        return cn.hutool.core.date.DateUtil.month(date) + 1;
    }

    /**
     * 当前日期，格式 yyyyMMdd
     *
     * @return 当前日期的标准形式字符串
     */
    public static String today() {
        return DatePattern.PURE_DATE_FORMAT.format(new DateTime());
    }

    /**
     * 获取日期的年份和月份
     * 如果参数为空，默认返回当前月份的
     *
     * @param date 日期
     * @return
     */
    public static String getYearAndMonth(Date date) {
        if (date == null) {
            date = cn.hutool.core.date.DateUtil.date();
        }
        return cn.hutool.core.date.DateUtil.format(date, "yyyyMM");
    }

    /**
     * 获取当前日期是今年的第多少周
     *
     * @param dateStr
     * @return
     */
    public static int weekOfYear(String dateStr) {
        if (StrUtil.isEmpty(dateStr)) {
            return cn.hutool.core.date.DateUtil.thisWeekOfYear();
        } else {
            return cn.hutool.core.date.DateUtil.weekOfYear(cn.hutool.core.date.DateUtil.parseDate(dateStr));
        }
    }

    /**
     * 获取昨天日期字符串
     *
     * @return
     */
    public static String yesterday() {
        return cn.hutool.core.date.DateUtil.formatDate(cn.hutool.core.date.DateUtil.yesterday());
    }

    /**
     * 根据月份和号初始化今年的日期
     *
     * @param year  年份
     * @param month 月份
     * @param day   日
     * @return
     */
    public static Date initDate(Integer year, Integer month, Integer day) {
        if (year == null) {
            year = cn.hutool.core.date.DateUtil.thisYear();
        }
        if (day == null) {
            day = 1;
        }
        return cn.hutool.core.date.DateUtil.parseDate(year + "-" + month + "-" + day);
    }

    /**
     * 判断compareDate是否在[startDate,endDate]期间
     *
     * @param compareDate 比较的日期
     * @param startDate   开始日期
     * @param endDate     终止日期
     * @return
     */
    public static boolean between(Date compareDate, Date startDate, Date endDate) {
        return compareDate.compareTo(startDate) >= 0 && compareDate.compareTo(endDate) <= 0;
    }

    /**
     * 获取指定年的当前月份为止的月份列表，
     * 如果传入2020，那么返回2020-01 2020-02 2020-03 2020-04
     *
     * @param year
     * @return
     */
    public static List<String> getYearMonths(String year) {
        List<String> months = new ArrayList<>();
        int currentMonth = cn.hutool.core.date.DateUtil.thisMonth() + 1;
        for (int i = 1; i <= currentMonth; i++) {
            months.add(year + String.format("-%02d", i));
        }
        return months;
    }

    /**
     * 将月份参数字符串->月份日期对象
     *
     * @param monthParam
     * @return
     */
    public static Date parseMonth(String monthParam) {
        return cn.hutool.core.date.DateUtil.parse(monthParam, "yyyy-MM");
    }

    public static String formatMonth(Date monthData) {
        return cn.hutool.core.date.DateUtil.format(monthData, "yyyyMM");
    }

    /**
     * 返回下个月的字符串格式，格式为：yyyyMM
     *
     * @return
     */
    public static String nextMonth() {
        return cn.hutool.core.date.DateUtil.format(cn.hutool.core.date.DateUtil.nextMonth(), "yyyyMM");
    }

    /**
     * 根据给定的日期范围生成日期范围字符串
     * 给定日期范围：[2021-08,2022-01];
     * 202108|202109|202110|202111|202112|202201
     *
     * @param beginMonthStr
     * @param endMonthStr
     * @return
     */
    public static String getMonthRangeStr(String beginMonthStr, String endMonthStr) {
        String monthRangeStr = "";
        Date beginMonth = parseMonth(beginMonthStr);
        Date endMonth = parseMonth(endMonthStr);
        long betweenMonth = cn.hutool.core.date.DateUtil.betweenMonth(beginMonth, endMonth, true);
        for (int i = 0; i <= betweenMonth; i++) {
            monthRangeStr += "|" + formatMonth(cn.hutool.core.date.DateUtil.offsetMonth(beginMonth, i));
        }
        if (monthRangeStr.length() > 1) {
            monthRangeStr = monthRangeStr.substring(1);
        }
        return monthRangeStr;
    }

    /**
     * 根据给定的日期范围生成日期范围列表
     * 给定日期范围：[2021-06-01,2022-09-22];
     * 返回[6,7,8,9]
     *
     * @param beginDate 起始月份
     * @param endDate   终止月份
     * @return
     */
    public static List<String> getNormMonthRangeList(Date beginDate, Date endDate) {
        List<String> monthRanges = CollectionUtil.newArrayList();
        long betweenMonth = cn.hutool.core.date.DateUtil.betweenMonth(beginDate, endDate, true);
        for (int i = 0; i <= betweenMonth; i++) {
            monthRanges.add(cn.hutool.core.date.DateUtil.month(cn.hutool.core.date.DateUtil.offsetMonth(beginDate, i)) + 1 + "");
        }
        return monthRanges;
    }

    /**
     * 获取近几个月的月份列表
     *
     * @param lastMonthNum
     * @return
     */
    public static List<String> getLastNormMonthRangeList(int lastMonthNum) {
        LinkedList<String> normMonthRanges = new LinkedList<>();
        DateTime current = cn.hutool.core.date.DateUtil.date();
        for (int i = 0; i < lastMonthNum; i++) {
            normMonthRanges.addFirst(cn.hutool.core.date.DateUtil.format(cn.hutool.core.date.DateUtil.offsetMonth(current,-1*i),DatePattern.NORM_MONTH_PATTERN));
        }
        return normMonthRanges;
    }

    /**
     * 罗列并设置指定日期区间内的周列表
     *
     * @param weeksList          周次列表
     * @param beginOfCurrentWeek 每周的第一天
     * @param beginOfYear        每年的第一天
     * @param endOfYear          每年的最后一天
     * @return
     */
    public static List<WeekRangeItemDTO> listWeeksOfYear(List<WeekRangeItemDTO> weeksList, Date beginOfCurrentWeek, Date beginOfYear, Date endOfYear) {
        if (CollectionUtil.isEmpty(weeksList)) {
            weeksList = CollectionUtil.newArrayList();
        }
        if (beginOfCurrentWeek.compareTo(endOfYear) > 0) {
            return weeksList;
        }
        // 获取startDate所在周的最后一天
        Date beginOfWeek = cn.hutool.core.date.DateUtil.beginOfWeek(beginOfCurrentWeek);
        if (beginOfWeek.compareTo(beginOfYear) < 0) {
            beginOfWeek = beginOfYear;
        }
        Date endOfWeek = cn.hutool.core.date.DateUtil.endOfWeek(beginOfWeek);
        if (endOfWeek.compareTo(endOfYear) > 0) {
            endOfWeek = endOfYear;
        }
        // 获取这周周次
        int weekOfYear = cn.hutool.core.date.DateUtil.weekOfYear(beginOfWeek);
        WeekRangeItemDTO weekRangeItem = new WeekRangeItemDTO();
        weekRangeItem.setWeekOfYear("t.value" + weekOfYear);
        weekRangeItem.setBeginOfWeek(cn.hutool.core.date.DateUtil.format(beginOfWeek, "M月d日"));
        weekRangeItem.setEndOfWeek(cn.hutool.core.date.DateUtil.format(endOfWeek, "M月d日"));
        weekRangeItem.setWeeklyOfYear(weekOfYear);
        weekRangeItem.setBeginOfWeekDate(beginOfWeek);
        weekRangeItem.setEndOfWeekDate(endOfWeek);
        weekRangeItem.setDays(cn.hutool.core.date.DateUtil.betweenDay(beginOfWeek, endOfWeek, true) + 1);
        weeksList.add(weekRangeItem);
        return listWeeksOfYear(weeksList, cn.hutool.core.date.DateUtil.offsetWeek(beginOfWeek, 1), beginOfYear, endOfYear);
    }

    /**
     * 将周次列表 转换成对应的月度列表
     *
     * @param weeklyList
     * @return
     */
    public static List<MonthRangeItemDTO> change2Month(List<WeekRangeItemDTO> weeklyList) {
        Map<String, List<WeekRangeItemDTO>> monthlyMap = new LinkedHashMap<>();
        // 进行分组
        for (WeekRangeItemDTO weeklyRangeItem : weeklyList) {
            String monthly = cn.hutool.core.date.DateUtil.format(weeklyRangeItem.getBeginOfWeekDate(), DatePattern.NORM_MONTH_PATTERN);
            if (!monthlyMap.containsKey(monthly)) {
                monthlyMap.put(monthly, CollectionUtil.newArrayList());
            }
            monthlyMap.get(monthly).add(weeklyRangeItem);
        }
        // 构建月度列表
        List<MonthRangeItemDTO> monthlyList = CollectionUtil.newArrayList();
        monthlyMap.forEach((monthly, tmpWeeklyList) -> {
            monthlyList.add(new MonthRangeItemDTO(monthly, tmpWeeklyList));
        });
        return monthlyList;
    }

    /**
     * 将周次列表 转换成对应的季度列表
     *
     * @param weeklyList
     * @return
     */
    public static List<QuarterRangeItemDTO> change2Quarter(List<WeekRangeItemDTO> weeklyList) {
        Map<Integer, List<WeekRangeItemDTO>> quarterMap = new LinkedHashMap<>();
        // 进行分组
        for (WeekRangeItemDTO weeklyRangeItem : weeklyList) {
            Integer quarter = cn.hutool.core.date.DateUtil.quarter(weeklyRangeItem.getBeginOfWeekDate());
            if (!quarterMap.containsKey(quarter)) {
                quarterMap.put(quarter, CollectionUtil.newArrayList());
            }
            quarterMap.get(quarter).add(weeklyRangeItem);
        }
        // 构建月度列表
        List<QuarterRangeItemDTO> quarterList = CollectionUtil.newArrayList();
        quarterMap.forEach((quarter, tmpWeeklyList) -> {
            quarterList.add(new QuarterRangeItemDTO(quarter, tmpWeeklyList));
        });
        return quarterList;
    }

    /**
     * 将周次列表 转换成对应的半年列表
     *
     * @param weeklyList
     * @return
     */
    public static List<HalfYearRangeItemDTO> change2HalfYear(List<WeekRangeItemDTO> weeklyList) {
        Map<Integer, List<WeekRangeItemDTO>> halfYearMap = new LinkedHashMap<>();
        // 进行分组
        for (WeekRangeItemDTO weeklyRangeItem : weeklyList) {
            Integer quarter = cn.hutool.core.date.DateUtil.quarter(weeklyRangeItem.getBeginOfWeekDate());
            Integer halfYear = 1;
            if (quarter == 3 || quarter == 4) {
                halfYear = 2;
            }
            if (!halfYearMap.containsKey(halfYear)) {
                halfYearMap.put(halfYear, CollectionUtil.newArrayList());
            }
            halfYearMap.get(halfYear).add(weeklyRangeItem);
        }
        // 构建月度列表
        List<HalfYearRangeItemDTO> halfYearList = CollectionUtil.newArrayList();
        halfYearMap.forEach((halfYear, tmpWeeklyList) -> {
            halfYearList.add(new HalfYearRangeItemDTO(halfYear, tmpWeeklyList));
        });
        return halfYearList;
    }

}
